<?php

Raise::load('core.dom.RaiseDomNode');
Raise::load('core.collection.RaiseCollection');
Raise::load('core.text.html.RaiseHtml');
Raise::load('core.reflection.RaiseVariable');

/**
 * RaiseHtmlTag class
 * Represents a HTML or XHTML tag node
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.core.text.html
 * @since 1.2
 */
class RaiseHtmlTag extends RaiseDomNode {

    /**
     * Create a new RaiseHtmlTag
     * @param string $tagName The tag name
     * @param string $value (optional) The content/innerHTML/value of the tag
     * @param array|RaiseCollection $attributes (optional) Attributes of the HTML tag
     */
    public function __construct($tagName, $value = '', $attributes = array()){
        parent::__construct($tagName, $value, $attributes);
        $this->doFix();
    }

    /**
     * Get the HTML code of tag
     * @return string
     */
    public function html(){
        return $this->__toString();
    }

    /**
     * Provide fixes XHTML tags
     */
    private function fixXHTML(){
        $this->tagName = strtolower($this->tagName());
        switch($this->tagName){
            case 'br':
                $this->children = null;
                break;
            case 'img':
                $this->children = null;
                if(!$this->attributes->keyExists('alt')){
                    $this->attributes->add('alt', '');
                }
                break;
            case 'link':
                /**
                 * `link` tags do not have any value
                 */
                $this->children = null;
                if($this->attributes->get('rel') == 'stylesheet' && !$this->attributes->keyExists('type')){
                    $this->attributes->add('type','text/css');
                }elseif($this->attributes->get('rel') != 'stylesheet' && $this->attributes->get('type') == 'text/css'){
                    $this->attributes->add('rel', 'stylesheet');
                }
                break;
            case 'title':
                /**
                 * Disable all HTML tags in the title tag
                 */
                $this->children[0] = RaiseHtml::encode($this->children[0]);
                break;
            case 'script':
                /**
                 * Value of the script tag should be empty if an external Javascript file source
                 * is specified.
                 */
                if($this->attributes->keyExists('src')){
                    $this->children[0] = '';
                }
                /**
                 * Fixes the script tag if the required 'type' attribute is missing
                 */
                if(!$this->attributes->keyExists('type')){
                    $this->attributes->add('type', 'text/javascript');
                }
                break;
            case 'style':
                /**
                 * Fixes the style tag if the required 'type' attribute is missing
                 */
                if(!$this->attributes->keyExists('type')){
                    $this->attributes->add('type', 'text/css');
                }
                break;
            case 'span':
                if($this->children()->count() == 0){
                    $this->children = null;
                }
                break;
            case 'textarea':
                if($this->children()->count() == 0){
                    $this->children = null;
                }
                break;
            case 'select':
                if($this->children()->count() == 0){
                    $this->children = null;
                }
                break;
        }
    }

    /**
     * Provides fixes for HTML tags
     */
    private function fixHTML(){
        switch($this->tagName){
            case 'script':
                if($this->attributes->keyExists('src')){
                    $this->children = null;
                }
                break;
        }
    }

    /**
     * Do fixing for XHTML or HTML
     */
    private function doFix(){
        if(RaiseHtml::isXHTMLSelected()){
            $this->fixXHTML();
        }else{
            $this->fixHTML();
        }
    }

    /**
     * To String
     * @return string
     */
    public function __toString(){
        if($this->tagName){
            $this->doFix();
            if(RaiseHtml::isXHTMLSelected()){
                $s = parent::__toString();
            }else{
                $s = '<'.$this->tagName.'';
                foreach($this->attributes as $k => $v){
                    if(RaiseVariable::isType($k, RaiseVariable::TYPESTRING)){
                       $s .= ' ' . $k ;
                       if($v){
                           $s .= '="' . str_replace(array('&', '&amp;amp;', '\\"', '"'),array('&amp;', '&amp;', '"', '\\"'), $v) . '"';
                       }
                    }
                }
                $s .= '>';
                if($this->children){
                    $s .= $this->value();
                    $s .= '</' . $this->tagName . '>';
                }
            }
            return $s;
        }
        return 'RaiseHtmlTag';
    }
}
